package com.lubase.metadata.service.impl;

import com.lubase.metadata.model.MapColumnModel;
import com.lubase.metadata.model.MapTableModel;
import com.lubase.metadata.service.ConstraintService;
import com.lubase.model.DbEntity;
import com.lubase.orm.QueryOption;
import com.lubase.orm.TableFilter;
import com.lubase.orm.exception.WarnCommonException;
import com.lubase.model.DbCollection;
import com.lubase.orm.service.DataAccess;
import com.lubase.orm.util.TableFilterWrapper;
import com.lubase.orm.util.TypeConverterUtils;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ConstraintServiceImpl implements ConstraintService {
    @Autowired
    DataAccess dataAccess;

    @SneakyThrows
    @Override
    public Integer addConstraint(String columnId, String refColumnId) {
        // 检查参数
        if (columnId == null || refColumnId == null) {
            throw new WarnCommonException("addConstraint: columnId or refColumnId is empty");
        }
        if (columnId.equals(refColumnId)) {
            return 0;
        }
        QueryOption queryOption = new QueryOption("mt_column");
        TableFilterWrapper filterWrapper = TableFilterWrapper.or();
        filterWrapper.eq("id", columnId).eq("id", refColumnId);
        queryOption.setTableFilter(filterWrapper.build());
        queryOption.setFixField("ms_database_id,ms_system_list_id,table_code,column_code");
        DbCollection collection = dataAccess.query(queryOption);
        if (collection != null && collection.getData() != null && collection.getData().size() == 2) {
            DbEntity currentColumn, refColumn = null;
            if (collection.getData().get(0).getId().toString().equals(columnId)) {
                currentColumn = collection.getData().get(0);
                refColumn = collection.getData().get(1);
            } else {
                currentColumn = collection.getData().get(1);
                refColumn = collection.getData().get(0);
            }
            if (checkExists(currentColumn.get("ms_database_id").toString(), currentColumn.get("table_code").toString(), currentColumn.get("column_code").toString())) {
                throw new WarnCommonException("addConstraint: constraint already exists");
            }
            DbCollection collConstraint = dataAccess.getEmptyData("mt_constraint");
            DbEntity constraint = collConstraint.newEntity();
            constraint.put("ms_database_id", currentColumn.get("ms_database_id"));
            constraint.put("ms_system_list_id", currentColumn.get("ms_system_list_id"));
            constraint.put("from_database", "0");
            constraint.put("table_code", currentColumn.get("table_code"));
            constraint.put("column_code", currentColumn.get("column_code"));
            constraint.put("ref_table_code", refColumn.get("table_code"));
            constraint.put("ref_column_code", refColumn.get("column_code"));
            constraint.put("constraint_name", String.format("fk_m_%s_%s_%s", currentColumn.get("table_code"), currentColumn.get("column_code"), refColumn.get("table_code")));
            collConstraint.getData().add(constraint);
            return dataAccess.update(collConstraint);
        }
        return 0;
    }

    Boolean checkExists(String databaseId, String tableCode, String columnCode) {
        QueryOption queryOption = new QueryOption("mt_constraint");
        TableFilterWrapper filterWrapper = TableFilterWrapper.and();
        filterWrapper.eq("ms_database_id", databaseId).eq("table_code", tableCode).eq("column_code", columnCode);
        queryOption.setTableFilter(filterWrapper.build());
        queryOption.setFixField("id");
        return !dataAccess.query(queryOption).getData().isEmpty();
    }

    @Override
    public List<MapColumnModel> getAllowColumnMetaList(String tableId) {
        List<MapColumnModel> list = getColumnMetaList(tableId);
        return list.stream().filter(model -> !model.getColumnCode().equals("id")).collect(Collectors.toList());
    }

    @Override
    public List<MapTableModel> getReferenceTableList(String tableId) {
        if (tableId == null) {
            return List.of();
        }
        QueryOption queryOption = new QueryOption("mt_table");
        queryOption.setTableFilter(new TableFilter("id", tableId));
        queryOption.setFixField("ms_database_id");
        DbCollection coll = dataAccess.queryAllData(queryOption);
        String databaseId = "";
        if (coll != null && coll.getData() != null && !coll.getData().isEmpty()) {
            databaseId = coll.getData().get(0).get("ms_database_id").toString();
        }
        queryOption = new QueryOption("mt_table");
        queryOption.setTableFilter(new TableFilter("ms_database_id", databaseId));
        queryOption.setFixField("id,table_code,table_name,alias_name");
        coll = dataAccess.queryAllData(queryOption);
        if (coll != null && coll.getData() != null) {
            List<MapTableModel> list = new ArrayList<>();
            coll.getData().forEach(entity -> {
                if (entity.get("id").toString().equals(tableId)) {
                    return;
                }
                MapTableModel model = new MapTableModel();
                model.setTableId(entity.get("id").toString());
                model.setTableCode(entity.get("table_code").toString());
                String aliasName = TypeConverterUtils.object2String(entity.get("alias_name"), "");
                String tableName = TypeConverterUtils.object2String(entity.get("table_name"), "");
                if (!aliasName.isEmpty()) {
                    model.setTableName(aliasName);
                } else if (!tableName.isEmpty()) {
                    model.setTableName(tableName);
                } else {
                    model.setTableName(model.getTableCode());
                }
                list.add(model);
            });
            return list;
        }
        return List.of();
    }

    @Override
    public List<MapColumnModel> getReferenceColumnList(String refTableId) {
        return getColumnMetaList(refTableId);
    }

    private List<MapColumnModel> getColumnMetaList(String tableId) {
        if (tableId == null) {
            return List.of();
        }
        QueryOption queryOption = new QueryOption("mt_column");
        queryOption.setTableFilter(new TableFilter("mt_table_id", tableId));
        queryOption.setFixField("id,column_code,column_type,merge_name");
        DbCollection coll = dataAccess.queryAllData(queryOption);
        List<MapColumnModel> list = new ArrayList<>();
        if (coll != null && coll.getData() != null) {
            coll.getData().forEach(entity -> {
                MapColumnModel model = new MapColumnModel();
                model.setColumnId(entity.get("id").toString());
                model.setColumnCode(entity.get("column_code").toString());
                model.setColumnName(entity.get("merge_name").toString());
                model.setColumnType(entity.get("column_type").toString());
                list.add(model);
            });
        }
        return list;
    }
}
